package com.gdust.lease.web.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gdust.lease.model.entity.*;
import com.gdust.lease.model.enums.ItemType;
import com.gdust.lease.web.admin.mapper.*;
import com.gdust.lease.web.admin.service.*;
import com.gdust.lease.web.admin.vo.attr.AttrValueVo;
import com.gdust.lease.web.admin.vo.graph.GraphVo;
import com.gdust.lease.web.admin.vo.room.RoomDetailVo;
import com.gdust.lease.web.admin.vo.room.RoomItemVo;
import com.gdust.lease.web.admin.vo.room.RoomQueryVo;
import com.gdust.lease.web.admin.vo.room.RoomSubmitVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * @author syun
 * @description 针对表【room_info(房间信息表)】的数据库操作Service实现
 * 房间信息表的id对应多个房间关系表的room_id
 * @createDate 2025-1-1 15:07:03
 */
@Service
public class RoomInfoServiceImpl extends ServiceImpl<RoomInfoMapper, RoomInfo>
        implements RoomInfoService {

    //注入图片信息表的service
    @Autowired
    private GraphInfoService graphInfoService;

    //注入房间属性表的service
    @Autowired
    private RoomAttrValueService roomAttrValueService;

    //注入房间设备表的service
    @Autowired
    private RoomFacilityService roomFacilityService;

    //注入房间标签表的service
    @Autowired
    private RoomLabelService roomLabelService;

    //注入房间支付方式表的service
    @Autowired
    private RoomPaymentTypeService roomPaymentTypeService;


    //注入房间租期表的service
    @Autowired
    private RoomLeaseTermService roomLeaseTermService;

    //注入房间信息表的mapper
    @Autowired
    private RoomInfoMapper roomInfoMapper;

    //注入公寓信息表的mapper
    @Autowired
    private ApartmentInfoMapper apartmentInfoMapper;

    //注入图片信息表的mapper
    @Autowired
    private GraphInfoMapper graphInfoMapper;

    //注入房间基本属性值表的mapper
    @Autowired
    private AttrValueMapper attrValueMapper;

    //注入设备信息表的mapper
    @Autowired
    private FacilityInfoMapper facilityInfoMapper;

    //注入标签信息表的mapper
    @Autowired
    private LabelInfoMapper labelInfoMapper;

    //注入支付方式表的mapper
    @Autowired
    private PaymentTypeMapper paymentTypeMapper;

    //注入租期表的mapper
    @Autowired
    private LeaseTermMapper leaseTermMapper;


    /**
     * 保存或更新房间信息
     * 思路：由于保存或更新房间信息涉及条件较多，此处直接先删除再修改
     * <p>
     * 注：先判断房间信息是否为空再执行房间信息VO的操作
     *
     * @param roomSubmitVo 房间信息VO,内含：图片列表、属性信息列表、配套信息列表、标签信息列表、支付方式列表、可选租期列表
     */
    @Override
    public void saveOrUpdateRoom(RoomSubmitVo roomSubmitVo) {
        //0.先判断房间是否为空
        boolean isUpdate = roomSubmitVo.getId() != null;

        //保存或更新房间信息表,RoomSubmitVo继承了RoomInfo,因此super调用的是房间信息表
        super.saveOrUpdate(roomSubmitVo);

        //若房间不为空，则执行下面操作
        if (isUpdate) {
            //先删除后修改
            //1.删除原有graphInfoList
            LambdaQueryWrapper<GraphInfo> graphInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
            //匹配图片所属对象类型是否为房间
            graphInfoLambdaQueryWrapper.eq(GraphInfo::getItemType, ItemType.ROOM);
            //匹配图片所有对象id是否为房间id
            graphInfoLambdaQueryWrapper.eq(GraphInfo::getItemId, roomSubmitVo.getId());
            graphInfoService.remove(graphInfoLambdaQueryWrapper);

            //2.删除原有roomAttrValueList
            LambdaQueryWrapper<RoomAttrValue> roomAttrValueLambdaQueryWrapper = new LambdaQueryWrapper<>();
            //匹配房间属性表的房间id是否为房间id
            roomAttrValueLambdaQueryWrapper.eq(RoomAttrValue::getAttrValueId, roomSubmitVo.getLabelInfoIds());
            roomAttrValueService.remove(roomAttrValueLambdaQueryWrapper);

            //3.删除原有roomFacilityList
            LambdaQueryWrapper<RoomFacility> roomFacilityLambdaQueryWrapper = new LambdaQueryWrapper<>();
            //匹配房间配套表的房间设施id是否为房间id
            roomFacilityLambdaQueryWrapper.eq(RoomFacility::getFacilityId, roomSubmitVo.getFacilityInfoIds());
            roomFacilityService.remove(roomFacilityLambdaQueryWrapper);

            //4.删除原有roomLabelList
            LambdaQueryWrapper<RoomLabel> roomLabelLambdaQueryWrapper = new LambdaQueryWrapper<>();
            roomLabelLambdaQueryWrapper.eq(RoomLabel::getLabelId, roomSubmitVo.getLabelInfoIds());
            roomLabelService.remove(roomLabelLambdaQueryWrapper);

            //5.删除原有paymentTypeList
            LambdaQueryWrapper<RoomPaymentType> roomPaymentTypeLambdaQueryWrapper = new LambdaQueryWrapper<>();
            roomPaymentTypeLambdaQueryWrapper.eq(RoomPaymentType::getPaymentTypeId, roomSubmitVo.getPaymentTypeIds());
            roomPaymentTypeService.remove(roomPaymentTypeLambdaQueryWrapper);


            //6.删除原有leaseTermList
            LambdaQueryWrapper<RoomLeaseTerm> roomLeaseTermLambdaQueryWrapper = new LambdaQueryWrapper<>();
            roomLeaseTermLambdaQueryWrapper.eq(RoomLeaseTerm::getLeaseTermId, roomSubmitVo.getLeaseTermIds());
            roomLeaseTermService.remove(roomLeaseTermLambdaQueryWrapper);

        }

        //1.保存新的graphInfoList
        List<GraphVo> graphVoList = roomSubmitVo.getGraphVoList();//获取房间图片id列表
        if (!CollectionUtils.isEmpty(graphVoList)) {
            //新建图片信息表集合，用于存储新建图片信息表对象
            ArrayList<GraphInfo> graphInfoArrayList = new ArrayList<>();
            // 遍历 graphVoList，逐一处理每个 GraphVo 对象
            for (GraphVo graphVo : graphVoList) {
                //新建图片信息表对象，用于设置属性
                GraphInfo graphInfo = new GraphInfo();
                graphInfo.setItemType(ItemType.ROOM);//设置图片所属对象类型为房间类型
                graphInfo.setItemId(roomSubmitVo.getId());//设置图片所有对象id为房间id
                graphInfo.setName(graphVo.getName());//设置图片名称
                graphInfo.setUrl(graphVo.getUrl());//设置图片地址
                //将图片信息表对象放入集合中
                graphInfoArrayList.add(graphInfo);
            }
            //批量保存图片信息表集合到数据库
            graphInfoService.saveBatch(graphInfoArrayList);
        }

        //2.保存新的roomAttrValueList
        List<Long> attrValueIdList = roomSubmitVo.getAttrValueIds();//获取属性id列表
        //如果属性id列表不为空,则进行下面操作
        if(!CollectionUtils.isEmpty(attrValueIdList)){
            //新建房间属性表的集合，用于存储新建房间属性表对象
            ArrayList<RoomAttrValue> roomAttrValueArrayList = new ArrayList<>();
            // 遍历 attrValueIdList，逐一处理每个 attrValueId 对象
            for(Long attrValueId : attrValueIdList){
                //新建房间属性表对象，用于设置属性
                RoomAttrValue roomAttrValue = new RoomAttrValue();
                roomAttrValue.setRoomId(roomSubmitVo.getId());//设置房间id
                roomAttrValue.setAttrValueId(attrValueId);//设置属性值id(表示当前遍历到的元素)
                //将房间属性表对象添加到集合中
                roomAttrValueArrayList.add(roomAttrValue);
            }
            //批量保存房间属性表集合到数据库
            roomAttrValueService.saveBatch(roomAttrValueArrayList);
        }

        //3.保存新的facilityInfoList
        List<Long> facilityInfoIdList = roomSubmitVo.getFacilityInfoIds();//获取配置id的集合
        //如果配置id集合不为空
        if(!CollectionUtils.isEmpty(facilityInfoIdList)){
            //新建房间设备表的集合，用于存储新建房间设备表对象
            ArrayList<RoomFacility> roomFacilityArrayList = new ArrayList<>();
            // 遍历 facilityInfoIdList，逐一处理每个 facilityId 对象
            for(Long facilityId:facilityInfoIdList){
                //新建房间设备表对象，用于设置属性
                RoomFacility roomFacility = new RoomFacility();
                roomFacility.setRoomId(roomSubmitVo.getId());//设置房间id
                roomFacility.setFacilityId(facilityId);//设置房间设施id(表示当前遍历到的元素)
                //将房间设备表对象添加到集合中
                roomFacilityArrayList.add(roomFacility);
            }
            //批量保存房间设备表集合到数据库
            roomFacilityService.saveBatch(roomFacilityArrayList);
        }


        //4.保存新的labelInfoList
        List<Long> labelInfoIdList = roomSubmitVo.getLabelInfoIds();//获取标签id的集合
        //如果标签id集合不为空
        if(!CollectionUtils.isEmpty(labelInfoIdList)){
            //新建房间标签表的集合，用于存储新建房间标签表对象
            ArrayList<RoomLabel> roomLabelArrayList = new ArrayList<>();
            // 遍历 labelInfoIdList，逐一处理每个 labelInfoId 对象
            for(long labelInfoId : labelInfoIdList){
                //新建房间标签表对象,用于设置属性
                RoomLabel roomLabel = new RoomLabel();
                roomLabel.setRoomId(roomSubmitVo.getId());//设置房间id
                roomLabel.setLabelId(labelInfoId);//设置标签id(表示当前遍历到的元素)
                //将房间标签表对象添加到集合中
                roomLabelArrayList.add(roomLabel);
            }
            //批量保存房间标签表集合到数据库中
            roomLabelService.saveBatch(roomLabelArrayList);
        }


        //5.保存新的paymentTypeList
        List<Long> paymentTypeIdList = roomSubmitVo.getPaymentTypeIds();//获取支付方式id集合
        //如果支付方式id集合不为空
        if(!CollectionUtils.isEmpty(paymentTypeIdList)){
            //新建房间支付方式集合，用于存储新建房间支付方式对象
            ArrayList<RoomPaymentType> roomPaymentTypeArrayList = new ArrayList<>();
            // 遍历 paymentTypeIdList，逐一处理每个 paymentTypeId 对象
            for(long paymentTypeId : paymentTypeIdList){
                //新建房间支付方式对象，用于设置属性
                RoomPaymentType roomPaymentType = new RoomPaymentType();
                roomPaymentType.setRoomId(roomPaymentType.getId());//设置放假id
                roomPaymentType.setPaymentTypeId(paymentTypeId);//设置支付类型id(表示当前遍历到的元素)
                //将房间支付方式对象放入集合中
                roomPaymentTypeArrayList.add(roomPaymentType);
            }
            //批量保存房间支付方式集合到数据库中
            roomPaymentTypeService.saveBatch(roomPaymentTypeArrayList);
        }

        //6.保存新的leaseTermList
        List<Long> leaseTermIdList = roomSubmitVo.getLeaseTermIds();//获取可选租期id的集合
        //如果可选租期id集合不为空
        if(!CollectionUtils.isEmpty(leaseTermIdList)){
            //新建房间租期表集合，用于存储新建房间租期表对象
            ArrayList<RoomLeaseTerm> roomLeaseTermArrayList = new ArrayList<>();
            // 遍历 leaseTermIdList，逐一处理每个 leaseTernId 对象
            for(Long leaseTernId : leaseTermIdList){
                //新建房间租期表对象，用于设置属性
                RoomLeaseTerm roomLeaseTerm = new RoomLeaseTerm();
                roomLeaseTerm.setRoomId(roomSubmitVo.getId());//设置房间id
                roomLeaseTerm.setLeaseTermId(leaseTernId);//设置租期id(表示当前遍历到的元素)
                //将房间租期信息对象放入到集合中
                roomLeaseTermArrayList.add(roomLeaseTerm);
            }
            //批量保存房间租期集合到数据库中
            roomLeaseTermService.saveBatch(roomLeaseTermArrayList);
        }

    }

    /**
     * 根据条件分页查询房间列表
     * @param page 分页对象
     * @param queryVo 查询条件
     * @return
     */
    @Override
    public IPage<RoomItemVo> pageRoomItemByQuery(IPage<Object> page, RoomQueryVo queryVo) {
        //自定义查询：根据条件分页查询房间列表
        return roomInfoMapper.pageRoomItemByQuery(page,queryVo);
    }

    /**
     * 根据id获取房间详细信息
     *
     * 注：还有房间信息,需要先查询房间信息
     *
     * 房间信息VO内容如下:所属公寓信息、图片列表、属性信息列表、配套信息列表、标签信息列表、支付方式列表、可选租期列表
     *
     * @param id 传入房间id
     * @return
     */
    @Override
    public RoomDetailVo getRoomDetailById(Long id) {
        //0.先查询房间信息
        RoomInfo roomInfo = roomInfoMapper.selectById(id);

        //1.查询所属公寓信息
        //调用Mybatis-Plus提供的封装方法，查询所属公寓信息
        ApartmentInfo apartmentInfo = apartmentInfoMapper.selectById(roomInfo);

        //2.查询图片列表
        //自定义方法：查询图片信息表，过滤条件：图片所属对象类型为房间，图片所属对象id为公寓id
        List<GraphVo> graphVoList = graphInfoMapper.selectListByItemTypeAndId(ItemType.ROOM,id);

        //3.查询属性信息列表
        //自定义查询：查询属性信息列表
        List<AttrValueVo> attrValueVoList = attrValueMapper.selectListByRoomId(id);

        //4.查询设备信息列表
        //自定义查询：查询设备信息列表
        List<FacilityInfo> facilityInfoList = facilityInfoMapper.selectListByRoomId(id);

        //5.查询标签信息列表
        //自定义查询：查询标签信息列表
        List<LabelInfo> labelInfoList = labelInfoMapper.selectListByRoomId(id);


        //6.查询支付方式列表
        //自定义查询：查询支付方式列表
        List<PaymentType> paymentTypeList = paymentTypeMapper.selectListByRoomId(id);


        //7.查询可选租期列表
        //自定义查询：查询可选租期列表
        List<LeaseTerm> leaseTermList = leaseTermMapper.selectListByRoomId(id);


        //8.组装结果
        RoomDetailVo roomDetailVo = new RoomDetailVo();
        //将对象的属性值(源对象)拷贝到目标对象的对应属性，前提是属性名和类型一致
        BeanUtils.copyProperties(roomInfo,roomDetailVo);
        //此处为RoomDetailVo特有的属性，需要单独设置
        roomDetailVo.setApartmentInfo(apartmentInfo);//设置所属公寓信息
        roomDetailVo.setGraphVoList(graphVoList);//设置图片列表
        roomDetailVo.setAttrValueVoList(attrValueVoList);//设置属性信息列表
        roomDetailVo.setFacilityInfoList(facilityInfoList);//设置配套信息列表
        roomDetailVo.setLabelInfoList(labelInfoList);//设置标签信息列表
        roomDetailVo.setPaymentTypeList(paymentTypeList);//设置支付方式列表
        roomDetailVo.setLeaseTermList(leaseTermList);//设置可选租期列表

        return roomDetailVo;
    }

    /**
     * 根据id删除房间信息
     *
     * 思路：首先需要删除房间信息表，再删除与房间信息表关联的内容:
     * 图片信息表、房间&基本属性值关联表、房间&配套关联表、房间&标签关联表、房间&支付方式关联表和房间租期管理表
     *
     *
     * @param id 房间id
     */
    @Override
    public void removeRoomById(Long id) {
        //0.删除房间信息表的内容
        super.removeById(id);


        //1.删除图片信息表的内容
        LambdaQueryWrapper<GraphInfo> graphInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //匹配所属类型是否为房间类型
        graphInfoLambdaQueryWrapper.eq(GraphInfo::getItemType, ItemType.ROOM);
        //匹配传入id是否为房间id
        graphInfoLambdaQueryWrapper.eq(GraphInfo::getId,id);
        graphInfoService.remove(graphInfoLambdaQueryWrapper);

        //2.删除房间&基本属性值关联表内容
        LambdaQueryWrapper<RoomAttrValue> roomAttrValueLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //匹配传入id是否为房间id
        roomAttrValueLambdaQueryWrapper.eq(RoomAttrValue::getRoomId,id);
        roomAttrValueService.remove(roomAttrValueLambdaQueryWrapper);


        //3.删除房间&配套关联表内容
        LambdaQueryWrapper<RoomFacility> roomFacilityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //匹配传入id是否为房间id
        roomFacilityLambdaQueryWrapper.eq(RoomFacility::getRoomId,id);
        roomFacilityService.remove(roomFacilityLambdaQueryWrapper);


        //4.删除房间&标签关联表内容
        LambdaQueryWrapper<RoomLabel> roomLabelLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //匹配传入id是否为房间id
        roomLabelLambdaQueryWrapper.eq(RoomLabel::getRoomId,id);
        roomLabelService.remove(roomLabelLambdaQueryWrapper);


        //5.删除房间&支付方式关联表内容
        LambdaQueryWrapper<RoomPaymentType> roomPaymentTypeLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //匹配传入id是否为房间id
        roomPaymentTypeLambdaQueryWrapper.eq(RoomPaymentType::getRoomId,id);
        roomPaymentTypeService.remove(roomPaymentTypeLambdaQueryWrapper);


        //6.删除房间租期管理表内容
        LambdaQueryWrapper<RoomLeaseTerm> roomLeaseTermLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //匹配传入id是否为房间id
        roomLeaseTermLambdaQueryWrapper.eq(RoomLeaseTerm::getRoomId,id);
        roomLeaseTermService.remove(roomLeaseTermLambdaQueryWrapper);


    }
}




